///////////////////////////////////////////////////////////////////////////////
//
// lighthouse3D - 3D Software Library
//
// File: CFogSynthesis.cpp
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2013 Marcus Reinhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
//
// You can find a copy of the GNU General Public License (gpl.txt) in the
// directory of the library.
//
///////////////////////////////////////////////////////////////////////////////
#include "CFogSynthesis.h"

///////////////////////////////////////////////////////////////////////////////
// CFogSynthesis::CFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
CFogSynthesis::CFogSynthesis()
{
	oldviewerDist = -100000000;
}

///////////////////////////////////////////////////////////////////////////////
// CFogSynthesis::~CFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
CFogSynthesis::~CFogSynthesis()
{
}

///////////////////////////////////////////////////////////////////////////////
// CFogSynthesis::~CFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
void CFogSynthesis::setFogParameters(float nearDist, float farDist, float fogDens, unsigned int colorFogR, unsigned int colorFogG, unsigned int colorFogB)
{
  // Now saving the square means sparing then square root later
  nearDistance = nearDist*nearDist;
  farDistance = farDist*farDist;
  fogDensity = fogDens;
  distanceMul = (float) 1.0 / ( farDistance-nearDistance );
  
  colorFogRed = colorFogR;
  colorFogGreen = colorFogG;
  colorFogBlue = colorFogB;
}

///////////////////////////////////////////////////////////////////////////////
// CFogSynthesis::linearFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
void CFogSynthesis::linearFogSynthesis(float viewerDist, unsigned int &intRed, unsigned int &intGreen, unsigned int &intBlue)
{
  float f;
  int i;

  if (viewerDist != oldviewerDist)
	  fogParam = ( farDistance-viewerDist ) * distanceMul;

  if (fogParam < 0) fogParam = 0;
  if (fogParam > 1) fogParam = 1;

  f = ( (fogParam * (float)intRed) + (1-fogParam) * (float)colorFogRed );

#ifdef __I386_ASM_OPTIMIZATION
  // Fast conversion float to int
  __asm
  {
	fld f
	fistp i
  };
#else
   i = (int) f;
#endif
  intRed = i;
  f = ( (fogParam * (float)intGreen) + (1-fogParam) * (float)colorFogGreen );
#ifdef __I386_ASM_OPTIMIZATION
  // Fast conversion float to int
  __asm
  {
	fld f
	fistp i
  };
#else
   i = (int) f;
#endif
  intGreen = i;

  f = ( (fogParam * (float)intBlue) + (1-fogParam) * (float)colorFogBlue );
#ifdef __I386_ASM_OPTIMIZATION
  // Fast conversion float to int
  __asm
  {
	fld f
	fistp i
  };
#else
   i = (int) f;
#endif
  intBlue = i;

  if (intRed > colorFogRed) 
	  intRed = colorFogRed;
  if (intGreen > colorFogGreen) 
	  intGreen = colorFogGreen;
  if (intBlue > colorFogBlue) 
	  intBlue = colorFogBlue;
}

///////////////////////////////////////////////////////////////////////////////
// CFogSynthesis::exponentialFogSynthesis( ... )
///////////////////////////////////////////////////////////////////////////////
void CFogSynthesis::exponentialFogSynthesis(float viewerDist, unsigned int &intRed, unsigned int &intGreen, unsigned int &intBlue)
{

  float fogParam;

  if (viewerDist != oldviewerDist)
	  fogParam = exp(-((viewerDist-nearDistance) * fogDensity));
	  // fogParam = fogParam * fogParam;

  if (fogParam < 0) fogParam = 0;
  if (fogParam > 1) fogParam = 1;

  intRed = (int) ( (fogParam * (float)intRed) + (1-fogParam) * (float)colorFogRed );
  intGreen = (int) ( (fogParam * (float)intGreen) + (1-fogParam) * (float)colorFogGreen );
  intBlue = (int) ( (fogParam * (float)intBlue) + (1-fogParam) * (float)colorFogBlue );

  if (intRed > colorFogRed) 
	  intRed = colorFogRed;
  if (intGreen > colorFogGreen) 
	  intGreen = colorFogGreen;
  if (intBlue > colorFogBlue) 
	  intBlue = colorFogBlue;
}

